#include "UIRenderer.h"

#include "Point2d_gl.h"
#include "UILabel.h"
#include "Color.h"
#include "Timer.h"

#include <list>
#include <gl.h>

namespace Lame3d
{
	UIRenderer::UIRenderer(const InputManager &iM, const DisplayManager &dM, SkinManager &sM, const std::string &skinName)
			: inputManager(iM), displayManager(dM), skinManager(sM),
			currentSkin(skinManager[skinName].GetHandle()), displayFPS(false)
	{
	}
	
	UIRenderer::~UIRenderer()
	{
	}
	
	void UIRenderer::RenderUI()
	{
		enter2d();
		
		//glEnable(GL_DEPTH_TEST);
		
		glPushMatrix();
		//glDisable(GL_DEPTH_TEST);
		glClear(GL_DEPTH_BUFFER_BIT);
		//glTranslatef(0, 0, .2);
		Color oC = glGetColor();
		
		// draw all windows
		std::list<Window*>::const_iterator it = inputManager.UI().WindowBegin();
		for(; it != inputManager.UI().WindowEnd(); ++it) {
			glSetColor( Color(1, 1, 1, (*it)->Opacity()) );
			drawWindow(*it);
			glTranslatef(0, 0, .05);
		}
		glSetColor(oC);
		glPopMatrix();
		//glEnable(GL_DEPTH_TEST);
		glTranslatef(0, 0, .95);
		drawCursor();	
				
		if(displayFPS) {
			drawFPS();
		}
			
		exit2d();
	}
	
	bool UIRenderer::DisplayFPS() const
	{
		return displayFPS;
	}
	
	void UIRenderer::DisplayFPS(bool b)
	{
		displayFPS = b;
	}
	
	UISkin::Handle& UIRenderer::CurrentSkin()
	{
		return currentSkin;
	}
	
	void UIRenderer::enter2d()
	{
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		glLoadIdentity();
		glOrtho(0, 
				displayManager.CurrentConfig().Width/float(displayManager.CurrentConfig().Height)
				, 0, 1, -1, 1);
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glLoadIdentity();
	}
	
	void UIRenderer::exit2d()
	{
		glMatrixMode(GL_PROJECTION);
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
		glPopMatrix();
	}
	
	void UIRenderer::drawCursor()
	{
		glPushMatrix();
		glTranslate(inputManager.MouseLocation());
		currentSkin.DrawCursor();
		glPopMatrix();
	}
	
	void UIRenderer::drawWindow(Window *w)
	{
		glPushMatrix();
		glTranslate(w->Location());
		currentSkin.DrawWindow(*w);
		glTranslatef(0, 0, .02); // small translation for overlay of contents		
		
		// draw labels
		std::list<UILabel*>::const_iterator labelIt;
		for(labelIt = w->LabelsBegin(); labelIt != w->LabelsEnd(); ++labelIt) {
			glPushMatrix();
			const Point2d &loc = (*labelIt)->Location();
			glTranslatef(loc[0], -loc[1], 0);
//			printf("drawing wrappiness %d...\n", (*labelIt)->Wrap());
			currentSkin.DrawLabel(**labelIt);
			glPopMatrix();
		}
		
		// draw buttons
		std::list<UIButton*>::const_iterator buttonIt;
		for(buttonIt = w->ButtonsBegin(); buttonIt != w->ButtonsEnd(); ++buttonIt) {
			glPushMatrix();
			const Point2d &loc = (*buttonIt)->Location();
			glTranslatef(loc[0], -loc[1], 0);
			currentSkin.DrawButton(**buttonIt);			
			glPopMatrix();
		}
		
		// draw text entries
		std::list<UITextEntry*>::const_iterator entriesIt;
		for(entriesIt = w->TextEntriesBegin(); entriesIt != w->TextEntriesEnd(); ++entriesIt) {
			glPushMatrix();
			const Point2d &loc = (*entriesIt)->Location();
			glTranslatef(loc[0], -loc[1], 0);
			currentSkin.DrawTextEntry(**entriesIt);			
			glPopMatrix();
		}
		
		glPopMatrix();
	}
	
	void UIRenderer::drawFPS() 
	{
		char c[20];
		float fps = 1.0 / fpsTimer.Seconds();
		sprintf(c, "FPS: %.1f", fps);
		std::string s(c);
		
		glPushMatrix();
			glTranslatef(0, 1, .02);
			currentSkin.DrawTextLight(s, 1, false);
		glPopMatrix();
		
	}
}
